package org.jsola.hr.provider.impl;

import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.jsola.exception.ParamException;
import org.jsola.hr.dto.RecruitXcxLoginByPhoneDTO;
import org.jsola.hr.dto.RecruitXcxLoginDTO;
import org.jsola.hr.entity.EmpInfoDO;
import org.jsola.hr.provider.IMessageProviderService;
import org.jsola.hr.provider.IRecruitProviderService;
import org.jsola.hr.provider.IUserProviderService;
import org.jsola.hr.service.IEmpInfoService;
import org.jsola.hr.vo.RecruitResultVO;
import org.jsola.recruit2.constant.PersonnelType;
import org.jsola.recruit2.dto.CompanyUnitsAddDTO;
import org.jsola.recruit2.dto.JobSeekerUpdateDTO;
import org.jsola.recruit2.entity.BrokerDO;
import org.jsola.recruit2.entity.CompanyUnitsDO;
import org.jsola.recruit2.entity.JobSeekerDO;
import org.jsola.recruit2.query.BrokerQuery;
import org.jsola.recruit2.query.CompanyUnitsQuery;
import org.jsola.recruit2.service.IBrokerLoggerService;
import org.jsola.recruit2.service.IBrokerService;
import org.jsola.recruit2.service.ICompanyUnitsService;
import org.jsola.recruit2.service.IJobSeekerService;
import org.jsola.recruit2.vo.BrokerVO;
import org.jsola.user.constant.UserConstants;
import org.jsola.user.core.TokenUser;
import org.jsola.user.dto.RecruitWechatXcxLoginDTO;
import org.jsola.user.dto.UserAddDTO;
import org.jsola.user.dto.login.WechatXcxLoginDTO;
import org.jsola.user.entity.ThirdInfoDO;
import org.jsola.user.entity.UserDO;
import org.jsola.user.vo.UserLoginVO;
import org.jsola.user.vo.UserVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;

import static org.jsola.hr.constant.HrConstants.USER_CERTIFICATION;


/**
 * @author wxz
 */
@Service("hrRecruitProviderServiceImpl")
@Slf4j
public class RecruitProviderServiceImpl implements IRecruitProviderService {


    @Autowired
    private IBrokerService brokerService;

    @Autowired
    private IBrokerLoggerService brokerLoggerService;

    @Autowired
    private IJobSeekerService jobSeekerService;

    @Autowired
    private IUserProviderService userProviderService;

    @Autowired
    private IRecruitProviderService recruitProviderService;

    @Autowired
    private IEmpInfoService empInfoService;

    @Autowired
    private ICompanyUnitsService companyUnitsService;

    @Autowired
    private IMessageProviderService messageProviderService;

    @Override
    public List<CompanyUnitsDO> getAllCompany(TokenUser tokenUser) {
        return companyUnitsService.select(new CompanyUnitsQuery(), tokenUser);
    }

    @Override
    public List<BrokerDO> getAllBroker(TokenUser tokenUser) {
        return brokerService.select(new BrokerQuery(), tokenUser);
    }

    @Override
    public CompanyUnitsDO saveCompany(CompanyUnitsAddDTO companyUnitsAddDTO, TokenUser tokenUser) {
        return companyUnitsService.save(companyUnitsAddDTO, tokenUser);
    }

    @Override
    public String getPhone(WechatXcxLoginDTO wechatXcxLoginDTO) {
        return userProviderService.getPhone(wechatXcxLoginDTO);
    }

    @Override
    public RecruitResultVO getPhone2(RecruitXcxLoginDTO recruitXcxLoginDTO, String unionId) {
        // 从授权信息中解析手机号
        String phone = userProviderService.getPhone(recruitXcxLoginDTO);
        return getRecruitResultVO(unionId, phone, recruitXcxLoginDTO.getNickName(), recruitXcxLoginDTO.getAvatar());
    }

    @Override
    public RecruitResultVO getPhoneAndCaptcha(RecruitXcxLoginByPhoneDTO recruitXcxLoginByPhoneDTO, String unionId) {
        // 通过手机号验证码确定手机号
        String phone = recruitXcxLoginByPhoneDTO.getPhone();
        ParamException.notNull(recruitXcxLoginByPhoneDTO.getCaptcha(), "验证码不能为空");
        boolean verifyCaptcha = messageProviderService.verifyCaptcha(USER_CERTIFICATION
                , phone, recruitXcxLoginByPhoneDTO.getCaptcha());
        ParamException.isTrue(verifyCaptcha, "验证码错误");
        return getRecruitResultVO(unionId, phone, recruitXcxLoginByPhoneDTO.getNickName(), recruitXcxLoginByPhoneDTO.getAvatar());
    }


    /**
     * 急聘首次登录绑定微信与手机号
     *
     * @param unionId  unionId
     * @param phone    手机号
     * @param nickName 昵称
     * @param avatar   头像
     * @return 登录信息
     */
    private RecruitResultVO getRecruitResultVO(String unionId, String phone, String nickName, String avatar) {
        RecruitResultVO recruitResultVO = new RecruitResultVO();
        // 根据unionId获取第三方信息
        ThirdInfoDO thirdInfo = userProviderService.selectByUnionId(unionId);
        log.info("绑定手机号验证码thirdInfoDOTmp：{}", thirdInfo);
        if (Objects.nonNull(thirdInfo)) {
            recruitResultVO.setHeadImgUrl(thirdInfo.getHeadImgUrl());
            recruitResultVO.setNickName(thirdInfo.getNickName());
        }
        UserDO userDO = userProviderService.selectByPhone(phone);
        if (userDO == null) {
            //用户不存在
            UserAddDTO userAddDTO = new UserAddDTO();
            userAddDTO.setPhone(phone);
            userAddDTO.setName(nickName);
            userAddDTO.setAvatar(avatar);
            UserVO userVO = userProviderService.onlySaveUser(userAddDTO);
            userDO = userVO.to(UserDO.class);
        }
        // 查询为经纪人
        BrokerVO brokerVO = selectLastBrokerByPhone(phone);
        if (brokerVO != null) {
            recruitResultVO.setPrincipalType(PersonnelType.BROKER.getValue());
            recruitResultVO.setPrincipalId(brokerVO.getId());
            recruitResultVO.setLoginType(PersonnelType.SEEKER.getValue());
            recruitResultVO.setLoginId(brokerVO.getId());
            recruitResultVO.setBrokerVO(brokerVO);
        } else {
            recruitResultVO.setLoginType(PersonnelType.SEEKER.getValue());
        }

        // 求职者
        TokenUser tokenUser = new TokenUser();
        tokenUser.setUserId(userDO.getId());
        JobSeekerDO jobSeekerDO = jobSeekerService.selectByCreateUserId(tokenUser.getUserId());
        if (jobSeekerDO != null) {
            recruitResultVO.setLoginId(jobSeekerDO.getId());
        }
        recruitResultVO.setJobSeekerDO(jobSeekerDO);
        //绑定微信并登录
        UserLoginVO userLoginVO = userProviderService.bindWechatAndLogin(userDO.getId(), UserConstants.TO_C, unionId);
        recruitResultVO.setUserLoginVO(userLoginVO);
        return recruitResultVO;
    }

    @Override
    @Transactional(value = UserConstants.TX, rollbackFor = Exception.class)
    public RecruitResultVO wechatRecruitLogin(RecruitWechatXcxLoginDTO recruitWechatXcxLoginDTO) {

        String phone = recruitWechatXcxLoginDTO.getPhone();
        // 查询为经纪人
        BrokerVO brokerVO = selectLastBrokerByPhone(phone);
        RecruitResultVO recruitResultVO = userProviderService.wechatRecruitLogin(recruitWechatXcxLoginDTO);
        UserLoginVO userLoginVO = recruitResultVO.getUserLoginVO();
        if (!userLoginVO.getVerified()) {
            log.error("创建用户失败，手机号：{}", phone);
            throw new ParamException("创建用户失败，请联系管理员");
        }
        // 求职者
        JobSeekerDO jobSeekerDO = null;
        if (brokerVO != null) {
            recruitWechatXcxLoginDTO.setSiteId(brokerVO.getSiteId());
        } else {
            jobSeekerDO = verifyInviter(recruitWechatXcxLoginDTO, userLoginVO.getUserVO().getId());
        }
        recruitResultVO.setPrincipalType(recruitWechatXcxLoginDTO.getPrincipalType());
        recruitResultVO.setPrincipalId(recruitWechatXcxLoginDTO.getPrincipalId());
        if (brokerVO != null) {
            // 经纪人登录 若没有邀请人 则邀请人就是自己
            if (StringUtil.isBlank(recruitWechatXcxLoginDTO.getPrincipalType())) {
                recruitResultVO.setPrincipalType(PersonnelType.BROKER.getValue());
                recruitResultVO.setPrincipalId(brokerVO.getId());
            }
            recruitResultVO.setLoginType(PersonnelType.BROKER.getValue());
            recruitResultVO.setLoginId(brokerVO.getId());
        } else {
            recruitResultVO.setLoginType(PersonnelType.SEEKER.getValue());
        }
        if (jobSeekerDO != null) {
            recruitResultVO.setLoginId(jobSeekerDO.getId());
        }
        recruitResultVO.setBrokerVO(brokerVO);
        recruitResultVO.setJobSeekerDO(jobSeekerDO);
        return recruitResultVO;
    }

    @Override
    public RecruitResultVO wechatRecruitLogin2(RecruitWechatXcxLoginDTO recruitWechatXcxLoginDTO) {
        RecruitResultVO recruitResultVO = userProviderService.wechatRecruitLogin2(recruitWechatXcxLoginDTO);
        UserLoginVO userLoginVO = recruitResultVO.getUserLoginVO();
        // 登录失败 直接返回
        if (!userLoginVO.getVerified()) {
            return recruitResultVO;
        }
        String phone = userLoginVO.getUserVO().getPhone();
        // 查询为经纪人
        BrokerVO brokerVO = recruitProviderService.selectLastBrokerByPhone(phone);
        // 求职者
        JobSeekerDO jobSeekerDO = null;
        if (brokerVO != null) {
            recruitWechatXcxLoginDTO.setSiteId(brokerVO.getSiteId());
        } else {
            jobSeekerDO = recruitProviderService.verifyInviter2(recruitWechatXcxLoginDTO, userLoginVO.getUserVO().getId());
        }
        recruitResultVO.setPrincipalType(recruitWechatXcxLoginDTO.getPrincipalType());
        recruitResultVO.setPrincipalId(recruitWechatXcxLoginDTO.getPrincipalId());
        if (brokerVO != null) {
//            recruitResultVO.setPrincipalType(PersonnelType.BROKER.getValue());
//            recruitResultVO.setPrincipalId(brokerVO.getId());
            recruitResultVO.setLoginType(PersonnelType.BROKER.getValue());
            recruitResultVO.setLoginId(brokerVO.getId());
            userLoginVO.setSiteId(brokerVO.getSiteId());
        } else {
            recruitResultVO.setLoginType(PersonnelType.SEEKER.getValue());
        }
        if (jobSeekerDO != null) {
            recruitResultVO.setLoginId(jobSeekerDO.getId());
        }
        recruitResultVO.setBrokerVO(brokerVO);
        recruitResultVO.setJobSeekerDO(jobSeekerDO);
        return recruitResultVO;
    }

    @Override
    public UserVO getUserVoByPhone(String phone) {
//        // 用户Id
//        UserDO userDO = userService.selectByPhone(phone);
//        String userId;
//        if (userDO == null) {
//            TokenUser createUser = new TokenUser();
//            createUser.setSiteId(siteId);
//            createUser.setUserId("system");
//            //用户不存在
//            UserAddDTO userAddDTO = new UserAddDTO();
//            userAddDTO.setPhone(phone);
//            userAddDTO.setName(phone);
//            //注册用户
//            return userService.save(userAddDTO, createUser);
//        }
//        // 修改userSite信息
//        List<UserSiteDO> userSiteDOList = userSiteService.selectByUserId(userDO.getId());
//        // 清空用户相同端其他站点 只保留所在/被邀请站点
//        for (UserSiteDO userSiteDO : userSiteDOList) {
//            if (TO_C.equals(userSiteDO.getTerminalType())) {
//                TokenUser tokenUser = new TokenUser();
//                tokenUser.setUserId("system");
//                tokenUser.setSiteId(userSiteDO.getSiteId());
//                userSiteService.deleteByIds(tokenUser, userSiteDO.getId());
//            }
//        }
//        cache.delKey(CacheKeyKit.getUserSiteListKey(userDO.getId()));
//        userId = userDO.getId();
//        return userDO.to(UserVO.class);
        return null;
    }


    @Override
    public JobSeekerDO verifyInviter(RecruitWechatXcxLoginDTO recruitWechatXcxLoginDTO, String userId) {

        ParamException.notNull(recruitWechatXcxLoginDTO.getSiteId(), "分享链接信息缺失，请重新分享");
        // 查询为求职者
        TokenUser tokenUser = new TokenUser();
        tokenUser.setUserId(userId);
        JobSeekerDO jobSeekerDO = jobSeekerService.selectByCreateUserId(tokenUser.getUserId());
        // 若带着邀请者信息 需要邀请者
        ParamException.hasText(recruitWechatXcxLoginDTO.getPrincipalType(), "请通过邀请二维码进入小程序");
        if (PersonnelType.BROKER.getValue().equals(recruitWechatXcxLoginDTO.getPrincipalType())
                && recruitWechatXcxLoginDTO.getPrincipalId() != null) {
            // 邀请者为经纪人
            BrokerDO inviteBrokerDO = selectBrokerByIdNotSiteId(recruitWechatXcxLoginDTO.getPrincipalId());
            // 经纪人已删除 显示为后台邀请
            if (inviteBrokerDO == null) {
                recruitWechatXcxLoginDTO.setPrincipalType(PersonnelType.SYSTEM.getValue());
                recruitWechatXcxLoginDTO.setPrincipalId(null);
            }
        } else if ("emp".equals(recruitWechatXcxLoginDTO.getPrincipalType())) {
            // 内推
            EmpInfoDO empInfoDO = empInfoService.selectById(recruitWechatXcxLoginDTO.getPrincipalId());
            // 内推已删除或已离职 显示为后台邀请
            if (empInfoDO == null || empInfoDO.getStatus() == 4) {
                recruitWechatXcxLoginDTO.setPrincipalType(PersonnelType.SYSTEM.getValue());
                recruitWechatXcxLoginDTO.setPrincipalId(null);
            }
        }
        // 若非第一次进入 更新邀请者信息
        if (jobSeekerDO != null) {
            JobSeekerUpdateDTO jobSeekerUpdateDTO = jobSeekerDO.to(JobSeekerUpdateDTO.class);
            jobSeekerUpdateDTO.setPrincipalType(recruitWechatXcxLoginDTO.getPrincipalType());
            jobSeekerUpdateDTO.setPrincipalId(recruitWechatXcxLoginDTO.getPrincipalId());
            TokenUser updateUser = new TokenUser();
            updateUser.setUserId("system");
            updateUser.setSiteId(jobSeekerDO.getSiteId());
            updateJobSeeker(jobSeekerUpdateDTO, updateUser);
        }
        return jobSeekerDO;
    }

    @Override
    public JobSeekerDO verifyInviter2(RecruitWechatXcxLoginDTO recruitWechatXcxLoginDTO, String userId) {
        ParamException.notNull(recruitWechatXcxLoginDTO.getSiteId(), "分享链接信息缺失，请重新分享");
        // 查询为求职者
        TokenUser tokenUser = new TokenUser();
        tokenUser.setUserId(userId);
        JobSeekerDO jobSeekerDO = jobSeekerService.selectByCreateUserId(tokenUser.getUserId());
        if (StringUtil.isBlank(recruitWechatXcxLoginDTO.getPrincipalType())) {
            return jobSeekerDO;
        }
        if (PersonnelType.BROKER.getValue().equals(recruitWechatXcxLoginDTO.getPrincipalType())
                && recruitWechatXcxLoginDTO.getPrincipalId() != null) {
            // 邀请者为经纪人
            BrokerDO inviteBrokerDO = selectBrokerByIdNotSiteId(recruitWechatXcxLoginDTO.getPrincipalId());
            ParamException.notNull(inviteBrokerDO, "邀请者信息有误，请重新获取邀请码");
        } else if ("emp".equals(recruitWechatXcxLoginDTO.getPrincipalType())) {
            // 内推
            EmpInfoDO empInfoDO = empInfoService.selectById(recruitWechatXcxLoginDTO.getPrincipalId());
            ParamException.notNull(empInfoDO, "内推员工不存在，请重新获取邀请码");
            ParamException.isFalse(empInfoDO.getStatus() == 4, "内推员工已离职，请重新获取邀请码");
        } else if (PersonnelType.SYSTEM.getValue().equals(recruitWechatXcxLoginDTO.getPrincipalType())) {
            // 后台管理员推送职位
        } else {
        }
        // 若非第一次进入 更新邀请者信息
        if (jobSeekerDO != null) {
            JobSeekerUpdateDTO jobSeekerUpdateDTO = jobSeekerDO.to(JobSeekerUpdateDTO.class);
            jobSeekerUpdateDTO.setPrincipalType(recruitWechatXcxLoginDTO.getPrincipalType());
            jobSeekerUpdateDTO.setPrincipalId(recruitWechatXcxLoginDTO.getPrincipalId());
            TokenUser updateUser = new TokenUser();
            updateUser.setUserId("system");
            updateUser.setSiteId(jobSeekerDO.getSiteId());
            updateJobSeeker(jobSeekerUpdateDTO, updateUser);
        }
        return jobSeekerDO;
    }

    @Override
    public List<BrokerDO> selectBrokerByPhone(String phone) {
        return brokerService.selectByPhone(phone);
    }

    @Override
    public BrokerVO selectLastBrokerByPhone(String phone) {
        UserDO userDO = userProviderService.selectByPhone(phone);
        ParamException.notNull(userDO, "用户不存在，请刷新后重试");
        return brokerLoggerService.selectLastByUserId(userDO.getId());
    }

    @Override
    public JobSeekerDO selectFirstOneSeekerByPhone(String phone) {
        return jobSeekerService.selectFirstOneByPhone(phone);
    }

    @Override
    public BrokerDO selectBrokerByIdNotSiteId(String brokerId) {
        return brokerService.selectByIdNotSiteId(brokerId);
    }

    @Override
    public int updateJobSeeker(JobSeekerUpdateDTO jobSeekerUpdateDTO, TokenUser tokenUser) {
        return jobSeekerService.update(jobSeekerUpdateDTO, tokenUser);
    }
}
